import tensorflow as tf  
from keras.datasets import mnist  
import numpy as np  
from tqdm import tqdm  
import matplotlib.pyplot as plt  
  
# 加载MNIST手写数字数据集  
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()  
  
# 对图像数据进行预处理：展平并归一化到[0, 1]区间  
train_images = train_images.reshape((train_images.shape[0], -1)) / 255.0  
test_images = test_images.reshape((test_images.shape[0], -1)) / 255.0  
  
# 将标签转换为one-hot编码形式  
train_labels = tf.keras.utils.to_categorical(train_labels, num_classes=10)  
test_labels = tf.keras.utils.to_categorical(test_labels, num_classes=10)  
  
# 初始化变量，用于记录最佳准确率及其对应的模型  
best_acc = 0.0  
best_model = None  
  
# 初始化列表，用于存储每个epoch的验证准确率  
epoch_accuracies = []  
  
# 构建多层感知机（MLP）模型  
model = tf.keras.models.Sequential([  
    tf.keras.layers.Dense(128, activation='relu', input_dim=784),  
    tf.keras.layers.Dropout(0.2),  
    tf.keras.layers.Dense(10, activation='softmax')  
])  
  
# 编译模型，设置优化器、损失函数和评估指标  
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])  
  
# 使用tqdm库显示训练进度条，并遍历每个epoch  
for epoch in tqdm(range(40), desc='Training Progress', unit='epoch'):  
    # 训练模型，并在验证集上进行评估  
    history = model.fit(train_images, train_labels, batch_size=128, epochs=1,   
                         validation_data=(test_images, test_labels), verbose=0)  
      
    # 获取当前epoch的验证准确率  
    val_accuracy = history.history['val_accuracy'][0]  
    epoch_accuracies.append(val_accuracy)  
      
    # 如果当前epoch的验证准确率高于之前记录的最佳准确率，则更新最佳准确率和模型  
    if val_accuracy > best_acc:  
        best_acc = val_accuracy  
        best_model = model  
  
# 保存具有最佳准确率的模型  
best_model.save('best_mlp_model_updated.h5')  
  
# 打印出最佳准确率  
print(f'Best Accuracy: {best_acc}')